#include "app_mqtt.h"
#include "log.h"
#include "MQTTClient.h"

static MQTTClient client; // mqtt客户端实例
// 如果使用SSL协议，需链接OpenSSL库并包含证书路径
#define mqtt_server_url "ws://x0faff0d.ala.dedicated.aliyun.emqxcloud.cn:8083" // mqtt服务器地址:
#define mqtt_client_id "6783f3a2-03de-11f0-8c33-00163e48dc1b"                  // mqtt客户端id
// 主题
#define mqtt_send_topic "gateway_to_web"
#define mqtt_receive_topic "web_to_gateway"

// 服务
#define mqtt_qos 1
// 发送消息信封使用默认的初始化模版
static MQTTClient_message msg = MQTTClient_message_initializer;

// 链接参数模版使用官方默认的
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer_ws;

// 接收消息的回调函数
static int (*recive_callback)(char *data, int len);

// mqtt客户端失联的回调函数
static void app_mqtt_connection_lost(void *context, char *cause)
{
    log_error("connection lost: %s", cause);
    // 连接切断,回收资源
    MQTTClient_destroy(&client);
}

// mqtt客户端收到消息的回调函数 成功 返回1，失败返回0
static int app_mqtt_message_arrived(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    // 从message中获取数据
    char *data = message->payload;
    int len = message->payloadlen;
    // 判断接受消息的回调函数是否注册
    if (recive_callback == NULL)
    {
        log_error("recive_callback is null");
        return 0;
    }
    // 调用注册在消息队列模块中的处理回调函数
    int res = recive_callback(data, len);
    if (res != 0)
    {
        log_error("recive_callback error");
        return 0;
    }
    // 释放msg
    MQTTClient_freeMessage(&message);
    return 1;
}

// 消息发送成功回调函数
static void app_mqtt_message_delivered(void *context, MQTTClient_deliveryToken dt)
{
    log_info("message delivered");
}

/**
 * mqtt客户端初始化的方法
 * @return 成功返回0，失败返回-1
 */
int app_mqtt_init()
{
    // 1.创建一个mqtt客户端
    int res = MQTTClient_create(&client, mqtt_server_url, mqtt_client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL); // persistence_type客户端要使用的持久化类型 null:应该设置为持久化目录的位置(none则为null)
    if (res != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_create error:%s", MQTTClient_strerror(res));
        return -1;
    }
    else
    {
        log_info("MQTTClient_create success");
    }
    // 2.设置mqtt客户端的回调函数, (1)失联事件(2) 收到消息事件(3) 消息发送成功事件
    MQTTClient_setCallbacks(client, NULL, app_mqtt_connection_lost, app_mqtt_message_arrived, app_mqtt_message_delivered);
    // 3.客户端正式连接服务器
    res = MQTTClient_connect(client, &conn_opts);
    if (res != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_connect error:%s", MQTTClient_strerror(res));
        return -1;
    }
    else
    {
        log_info("MQTTClient_connect success");
    }
    // 4.客户端订阅主题
    res = MQTTClient_subscribe(client, mqtt_receive_topic, mqtt_qos);
    if (res != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_subscribe error:%s", MQTTClient_strerror(res));
        return -1;
    }
    else
    {
        log_info("MQTTClient_subscribe success");
    }
    return 0;
}
/**
 * mqtt客户端发送消息的方法
 * @param 发送的数据
 * @param 发送的数据长度
 * @return 成功返回0，失败返回-1
 */
int app_mqtt_send(char *data, int len)
{
    msg.payload = data;
    msg.payloadlen = len;
    int res = MQTTClient_publishMessage(client, mqtt_send_topic, &msg, NULL);
    if (res != MQTTCLIENT_SUCCESS)
    {
        log_error("MQTTClient_publishMessage error");
        return -1;
    }
    return 0;
}

/**
 *@brief 外部模块向消息队列模块中注册回调函数
 *@param 回调函数
 *@return 成功返回0，失败返回-1
 */
int app_mqtt_register_callback(int (*callback)(char *data, int len))
{
    recive_callback = callback;
    return 0;
}

/**
 * @brief 销毁mqtt客户端
 * @return 成功返回0，失败返回-1
 */
int app_mqtt_destroy()
{
    MQTTClient_disconnect(client, 10000); // 断开连接
    MQTTClient_destroy(&client);          // 销毁客户端
    return 0;
}